package pl.prv.polanie.client.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import pl.prv.polanie.client.Planner;
import pl.prv.polanie.client.compositerequest.PCompositeRequest;
import pl.prv.polanie.client.compositerequest.PCompositeRequestBuilder;
import pl.prv.polanie.client.dto.CSAcademicTitleDTO;
import pl.prv.polanie.client.dto.CSBuildingDTO;
import pl.prv.polanie.client.dto.CSCalendarDayDTO;
import pl.prv.polanie.client.dto.CSDeclarationDTO;
import pl.prv.polanie.client.dto.CSGroupDTO;
import pl.prv.polanie.client.dto.CSLecturerDTO;
import pl.prv.polanie.client.dto.CSPreferenceDTO;
import pl.prv.polanie.client.dto.CSPreferenceTypeDTO;
import pl.prv.polanie.client.dto.CSRoomDTO;
import pl.prv.polanie.client.dto.CSRoomTypeDTO;
import pl.prv.polanie.client.dto.CSSemesterDTO;
import pl.prv.polanie.client.dto.CSSemesterTypeDTO;
import pl.prv.polanie.client.dto.CSSemestersYearGroupsDTO;
import pl.prv.polanie.client.dto.CSStudiesTypeDTO;
import pl.prv.polanie.client.dto.CSSubgroupDTO;
import pl.prv.polanie.client.dto.CSSubgroupTypeDTO;
import pl.prv.polanie.client.dto.CSSubjectDTO;
import pl.prv.polanie.client.dto.CSSubjectEventDTO;
import pl.prv.polanie.client.dto.CSSubjectNameDTO;
import pl.prv.polanie.client.dto.CSSubjectTypeDTO;
import pl.prv.polanie.client.dto.CSYearGroupNameDTO;
import pl.prv.polanie.client.panels.SchedulesList;
import pl.prv.polanie.client.widgets.schedule.custom.ICache;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class Cache implements ICache {
	
	//<Long, Object>
	private static Map<Long, CSAcademicTitleDTO> academicTitles = new HashMap<Long, CSAcademicTitleDTO>();
	private static Map<Long, CSLecturerDTO> lecturers = new HashMap<Long, CSLecturerDTO>();
	private static Map<Long, CSBuildingDTO> buildings = new HashMap<Long, CSBuildingDTO>();
	private static Map<Long, CSRoomTypeDTO> roomTypes = new HashMap<Long, CSRoomTypeDTO>();
	private static Map<Long, CSRoomDTO> rooms = new HashMap<Long, CSRoomDTO>();
	private static Map<Long, CSSubjectTypeDTO> subjectTypes = new HashMap<Long, CSSubjectTypeDTO>();
	private static Map<Long, CSSubjectNameDTO> subjectNames = new HashMap<Long, CSSubjectNameDTO>();
	private static Map<Long, CSSubjectDTO> subjects = new HashMap<Long, CSSubjectDTO>();
	
	private static Map<Long, CSSubgroupTypeDTO> subgroupTypes = new HashMap<Long, CSSubgroupTypeDTO>();
	private static Map<Long, CSStudiesTypeDTO> studiesTypes = new HashMap<Long, CSStudiesTypeDTO>();
	private static Map<Long, CSSemesterTypeDTO> semesterTypes = new HashMap<Long, CSSemesterTypeDTO>();
	private static Map<Long, CSSemesterDTO> semesters = new HashMap<Long, CSSemesterDTO>();
	private static Map<Long, CSCalendarDayDTO> calendarDays = new HashMap<Long, CSCalendarDayDTO>();

	private static Map<Long, CSYearGroupNameDTO> yearGroupNames = new HashMap<Long, CSYearGroupNameDTO>();
	private static Map<Long, CSSemestersYearGroupsDTO> semestersYearGroups = new HashMap<Long, CSSemestersYearGroupsDTO>();
	private static Map<Long, CSGroupDTO> groups = new HashMap<Long, CSGroupDTO>();
	private static Map<Long, CSSubgroupDTO> subgroups = new HashMap<Long, CSSubgroupDTO>();
	
	private static Map<Long, CSSubjectEventDTO> subjectEvents = new HashMap<Long, CSSubjectEventDTO>();
	
	private static Map<Long, CSDeclarationDTO> declarations = new HashMap<Long, CSDeclarationDTO>();

	private static Map<Long, CSPreferenceTypeDTO> preferenceTypes = new HashMap<Long, CSPreferenceTypeDTO>();
	private static Map<Long, CSPreferenceDTO> preferences = new HashMap<Long, CSPreferenceDTO>();


	public static PCompositeRequestBuilder loadInitialData() {
		
		
		final PCompositeRequest mainReq = new PCompositeRequest("main");
		mainReq.setMakeCallCmd(new Command() {
			public void execute() {
				mainReq.runOnSuccessCmd();
				Planner.get().hideLoadingMessage();
			}
		});
		
		
		//LECTURERS
		final PCompositeRequest academicTitlesReq = new PCompositeRequest("academicTitles");
		academicTitlesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getAcademicTitles(academicTitlesReq);
			};
		});
		
		
		final PCompositeRequest lecturersReq = new PCompositeRequest("lecturers");
		lecturersReq.setMakeCallCmd(new Command() {
			public void execute() {
				getLecturers(lecturersReq);
			}
		});
		lecturersReq.setOnSuccessCmd(new Command() {
			public void execute() {
				Planner.get().getSchedulesList().reloadBranchWithLecturersSchedules();
			}
		});
		

		
		//ROOMS
		final PCompositeRequest roomTypesReq = new PCompositeRequest("roomTypes");
		roomTypesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getRoomTypes(roomTypesReq);
			};
		});
		
		final PCompositeRequest buildingsReq = new PCompositeRequest("buildings");
		buildingsReq.setMakeCallCmd(new Command() {
			public void execute() {
				getBuildings(buildingsReq);
			};
		});

		final PCompositeRequest roomsReq = new PCompositeRequest("rooms");
		roomsReq.setMakeCallCmd(new Command() {
			public void execute() {
				getRooms(roomsReq);
			}
		});
		roomsReq.setOnSuccessCmd(new Command() {
			public void execute() {
				Planner.get().getSchedulesList().reloadBranchWithRoomsSchedules();
			}
		});
		
		
		//SUBJECTS
		final PCompositeRequest subjectTypesReq = new PCompositeRequest("subjectTypes");
		subjectTypesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSubjectTypes(subjectTypesReq);
			}
		});

		final PCompositeRequest subjectNamesReq = new PCompositeRequest("subjectNames");
		subjectNamesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSubjectNames(subjectNamesReq);
			}
		});
		
		final PCompositeRequest subjectsReq = new PCompositeRequest("subjects");
		subjectsReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSubjects(subjectsReq);
			}
		});
		
		
		//SEMESTER
		final PCompositeRequest studiesTypesReq = new PCompositeRequest("studiesTypes");
		studiesTypesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getStudiesTypes(studiesTypesReq);
			}
		});

		final PCompositeRequest semesterTypesReq = new PCompositeRequest("semesterTypes");
		semesterTypesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSemesterTypes(semesterTypesReq);
			}
		});
		
		final PCompositeRequest semestersReq = new PCompositeRequest("semesters");
		semestersReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSemesters(semestersReq);
			}
		});
		semestersReq.setOnSuccessCmd(new Command() {
			public void execute() {
				long defaultSemesterID = -1;
				
				if (ContextSettings.isAdminUserSignedIn()) {
					defaultSemesterID = CookiesSettings.getDefaultSemesterForAdmin();
				} else {
					defaultSemesterID = CookiesSettings.getDefaultSemesterForUser();
				}
				
				if (defaultSemesterID != -1) {
					Planner.log("Cache.loadInitialData: ustawiam DEFAULT semesterID " + defaultSemesterID);
					ContextSettings.setSemesterID(defaultSemesterID);
				}
				Planner.get().loadDataToSemesterSelectionWidget();
			}
		});
		

		//OTHER
		final PCompositeRequest subgroupTypesReq = new PCompositeRequest("subgroupTypes");
		subgroupTypesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSubgroupTypes(subgroupTypesReq);
			}
		});
		
		final PCompositeRequest calendarDaysReq = new PCompositeRequest("calendarDays");
		calendarDaysReq.setMakeCallCmd(new Command() {
			public void execute() {
				getCalendarDaysBySemesterID(ContextSettings.getSemesterID(), calendarDaysReq);
			}
		});
		
		final PCompositeRequest yearGroupNamesReq = new PCompositeRequest("yearGroupName");
		yearGroupNamesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getYearGroupNames(yearGroupNamesReq);
			}
		});
		
		final PCompositeRequest declarationReq = new PCompositeRequest("declarations");
		declarationReq.setMakeCallCmd(new Command() {
			public void execute() {
				getDeclarationsBySemesterID(ContextSettings.getSemesterID(), declarationReq);
			}
		});
		
		final PCompositeRequest semestersYearGroupsReq = new PCompositeRequest("semestersYearGroups");
		semestersYearGroupsReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSemestersYearGroupsBySemesterID(ContextSettings.getSemesterID(), semestersYearGroupsReq);
			}
		});

		final PCompositeRequest subgroupsReq = new PCompositeRequest("subgroups");
		subgroupsReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSubgroupsBySemesterID(ContextSettings.getSemesterID(), subgroupsReq);
			}
		});
		
		
		//GROUPS
		final PCompositeRequest groupsReq = new PCompositeRequest("groups");
		groupsReq.setMakeCallCmd(new Command() {
			public void execute() {
				getGroupsBySemesterID(ContextSettings.getSemesterID(), groupsReq);
			};
		});
		groupsReq.setOnSuccessCmd(new Command() {
			public void execute() {
				Planner.log("Cache.sciagnalem groups dla semesterID " + ContextSettings.getSemesterID());
				Planner.get().getSchedulesList().reloadBranchWithGroupSchedules();
			}
		});
		
		
		
		//PREFERENCE TYPES();
		final PCompositeRequest preferenceTypesReq = new PCompositeRequest("subgroups");
		preferenceTypesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getPreferenceTypes(preferenceTypesReq);
			}
		});

		final PCompositeRequest subjectEventsReq = new PCompositeRequest("subjectEvents");
		subjectEventsReq.setMakeCallCmd(new Command() {
			public void execute() {
				getSubjectEventsBySemesterID(ContextSettings.getSemesterID(), subjectEventsReq);
			}
		});

		final PCompositeRequest preferencesReq = new PCompositeRequest("preferences");
		preferencesReq.setMakeCallCmd(new Command() {
			public void execute() {
				getPreferencesBySemesterID(ContextSettings.getSemesterID(), preferencesReq);
			}
		});
		
		//
		mainReq.addDescendantRequest(lecturersReq);
			lecturersReq.addDescendantRequest(academicTitlesReq);
		
		mainReq.addDescendantRequest(roomsReq);
			roomsReq.addDescendantRequest(roomTypesReq);
			roomsReq.addDescendantRequest(buildingsReq);

			
		mainReq.addDescendantRequest(subjectsReq);
			subjectsReq.addDescendantRequest(subjectTypesReq);
			subjectsReq.addDescendantRequest(subjectNamesReq);
		
		mainReq.addDescendantRequest(groupsReq);
			groupsReq.addDescendantRequest(semestersReq);
				semestersReq.addDescendantRequest(studiesTypesReq);
				semestersReq.addDescendantRequest(semesterTypesReq);
				
			groupsReq.addDescendantRequest(subgroupTypesReq);
			groupsReq.addDescendantRequest(yearGroupNamesReq);
			groupsReq.addDescendantRequest(semestersYearGroupsReq);
			groupsReq.addDescendantRequest(subgroupsReq);
			
		mainReq.addDescendantRequest(declarationReq);
		mainReq.addDescendantRequest(calendarDaysReq);
		mainReq.addDescendantRequest(preferenceTypesReq);
		mainReq.addDescendantRequest(subjectEventsReq);
		mainReq.addDescendantRequest(preferencesReq);

		PCompositeRequestBuilder requestBuilder = new PCompositeRequestBuilder();
		requestBuilder.setRequest(mainReq);
//		requestBuilder.makeAllCalls();
		
		return requestBuilder;
		
	}
	
	
//	public static void loadInitialData2() {
//		
//		//MAIN - schowanie loadera
//		MultiRequest mainMR = new MultiRequest(21);
//		mainMR.addFinalCommand(new Command() {
//			public void execute() {
//				Planner.get().hideLoadingMessage();
////				SchedulesList.generateReports();
//			}
//		});
//		
//		//LECTURERS
//		MultiRequest mRequestLecturers = new MultiRequest(2);
//		mRequestLecturers.addFinalCommand(new Command() {
//			public void execute() {
//				Planner.get().getSchedulesList().reloadBranchWithLecturersSchedules();
//			}
//		});
//		
//		MultiRequest[] academicTitlesMRs = new MultiRequest[2];
//		academicTitlesMRs[0] = mRequestLecturers;
//		academicTitlesMRs[1] = mainMR;
//		getAcademicTitles(academicTitlesMRs);
//		
//		MultiRequest[] lecturersMRs = new MultiRequest[2];
//		lecturersMRs[0] = mRequestLecturers;
//		lecturersMRs[1] = mainMR;
//		getLecturers(lecturersMRs);
//
//
//
//		//ROOMS
//		MultiRequest mRequestRooms = new MultiRequest(3);
//		mRequestRooms.addFinalCommand(new Command() {
//			public void execute() {
//				Planner.get().getSchedulesList().reloadBranchWithRoomsSchedules();
//			}
//		});
//		
//		MultiRequest[] buildingsMRs = new MultiRequest[2];
//		buildingsMRs[0] = mRequestRooms;
//		buildingsMRs[1] = mainMR;
//		getBuildings(buildingsMRs);
//		
//		MultiRequest[] roomsMRs = new MultiRequest[2];
//		roomsMRs[0] = mRequestRooms;
//		roomsMRs[1] = mainMR;
//		getRooms(roomsMRs);
//		
//		MultiRequest[] roomTypesMRs = new MultiRequest[2];
//		roomTypesMRs[0] = mRequestRooms;
//		roomTypesMRs[1] = mainMR;
//		getRoomTypes(roomTypesMRs);
//		
//		
//		
//		//SUBJECTS
//		MultiRequest[] subjectTypesMRs = new MultiRequest[1];
//		subjectTypesMRs[0] = mainMR;
//		getSubjectTypes(subjectTypesMRs);
//		
//		MultiRequest[] subjectNamesMRs = new MultiRequest[1];
//		subjectNamesMRs[0] = mainMR;
//		getSubjectNames(subjectNamesMRs);
//		
//		MultiRequest[] subjectsMRs = new MultiRequest[1];
//		subjectsMRs[0] = mainMR;
//		getSubjects(subjectsMRs);
//		
//		
//		
//		//SEMESTER
//		MultiRequest mRequestSemesters = new MultiRequest(3);
//		mRequestSemesters.addFinalCommand(new Command() {
//			public void execute() {
//				long defaultSemesterID = -1;
//				
//				if (ContextSettings.isAdminUserSignedIn()) {
//					defaultSemesterID = CookiesSettings.getDefaultSemesterForAdmin();
//				} else {
//					defaultSemesterID = CookiesSettings.getDefaultSemesterForUser();
//				}
//				
//				if (defaultSemesterID != -1) {
//					Planner.log("Cache.loadInitialData: ustawiam DEFAULT semesterID " + defaultSemesterID);
//					ContextSettings.setSemesterID(defaultSemesterID);
//				}
//				Planner.get().loadDataToSemesterSelectionWidget();
//			}
//		});
//		
//		MultiRequest[] studiesTypesMRs = new MultiRequest[2];
//		studiesTypesMRs[0] = mRequestSemesters;
//		studiesTypesMRs[1] = mainMR;
//		getStudiesTypes(studiesTypesMRs);
//		
//		MultiRequest[] semesterTypesMRs = new MultiRequest[2];
//		semesterTypesMRs[0] = mRequestSemesters;
//		semesterTypesMRs[1] = mainMR;
//		getSemesterTypes(semesterTypesMRs);
//
//		//
//		MultiRequest[] semestersMRs = new MultiRequest[2];
//		semestersMRs[0] = mRequestSemesters;
//		semestersMRs[1] = mainMR;
//		getSemesters(semestersMRs);
//		
//		
//		//OTHER
//		MultiRequest[] subgroupTypesMRs = new MultiRequest[1];
//		subgroupTypesMRs[0] = mainMR;
//		getSubgroupTypes(subgroupTypesMRs);
//		
//		MultiRequest[] calendarDaysMRs = new MultiRequest[1];
//		calendarDaysMRs[0] = mainMR;
//		getCalendarDaysBySemesterID(ContextSettings.getSemesterID(), calendarDaysMRs);
//
//		MultiRequest[] yearGroupNamesMRs = new MultiRequest[1];
//		yearGroupNamesMRs[0] = mainMR;
//		getYearGroupNames(yearGroupNamesMRs);
//
//
//		
//		
//		MultiRequest[] declarationsMRs = new MultiRequest[1];
//		declarationsMRs[0] = mainMR;
//		getDeclarationsBySemesterID(ContextSettings.getSemesterID(), declarationsMRs);
//		
//		MultiRequest[] semestersYearGroupsMRs = new MultiRequest[1];
//		semestersYearGroupsMRs[0] = mainMR;
//		getSemestersYearGroupsBySemesterID(ContextSettings.getSemesterID(), semestersYearGroupsMRs);
//		
//		MultiRequest[] subgroupsMRs = new MultiRequest[1];
//		subgroupsMRs[0] = mainMR;
//		getSubgroupsBySemesterID(ContextSettings.getSemesterID(), subgroupsMRs);
//
//		
//		
//		//GROUPS
//		MultiRequest mRequestGroups = new MultiRequest(1);
//		mRequestGroups.addFinalCommand(new Command() {
//			public void execute() {
//				
//				Planner.log("Cache.sciagnalem groups dla semesterID " + ContextSettings.getSemesterID());
//				Planner.get().getSchedulesList().reloadBranchWithGroupSchedules();
//			}
//		});
//		
//		MultiRequest[] groupsMRs = new MultiRequest[2];
//		groupsMRs[0] = mRequestGroups;
//		groupsMRs[1] = mainMR;
//		Planner.log("zzzzzzzzzzzzzzzzzzzzzzzzz SCIAGAM GRUPY DLA SEMESTERUD " + ContextSettings.getSemesterID());
//		getGroupsBySemesterID(ContextSettings.getSemesterID(), groupsMRs);
//		
//		//PREFERENCE TYPES();
//		MultiRequest[] preferenceTypesMRs = new MultiRequest[1];
//		preferenceTypesMRs[0] = mainMR;
//		getPreferenceTypes(preferenceTypesMRs);
//		
//		//SUBJECT EVENTS
//		MultiRequest[] subjectEventsMRs = new MultiRequest[1];
//		subjectEventsMRs[0] = mainMR;
//		getSubjectEventsBySemesterID(ContextSettings.getSemesterID(), subjectEventsMRs);
//		
//		//PREFERENCES
//		MultiRequest[] preferencesMRs = new MultiRequest[1];
//		preferencesMRs[0] = mainMR;
//		getPreferencesBySemesterID(ContextSettings.getSemesterID(), subjectEventsMRs);
//	}
	
	
	public static void clearAllStoredData() {
		academicTitles.clear();
		lecturers.clear();
		buildings.clear();
		roomTypes.clear();
		rooms.clear();
		subjectTypes.clear();
		subjectNames.clear();
		subjects.clear();
		
		subgroupTypes.clear();
		studiesTypes.clear();
		semesterTypes.clear();
		semesters.clear();
		calendarDays.clear();

		yearGroupNames.clear();
		semestersYearGroups.clear();
		groups.clear();
		subgroups.clear();
		
		subjectEvents.clear();
		
		declarations.clear();

		preferenceTypes.clear();
		preferences.clear();
	}
	
	public static void clearSubjectEvents() {
		subjectEvents.clear();
	}
	
	public static void loadDataWhenAnotherSemesterSelected() {
		//pobierane sa wszystkie od razu, wiec nie trzeba przeladowac
		//getCalendarDays();
		//getSubgroups();
		Planner.log("- - - WYBRANO INNY SEMESTR");
		
		//GroupSchedules
		

		
		final PCompositeRequest request = new PCompositeRequest("main");
		
		request.setMakeCallCmd(new Command() {
			public void execute() {
				//pobranie declarations
				getDeclarationsBySemesterID(ContextSettings.getSemesterID(), request);
				
				//pobranie sygs
				getSemestersYearGroupsBySemesterID(ContextSettings.getSemesterID(), request);		
				
				//pobranie groups
				getGroupsBySemesterID(ContextSettings.getSemesterID(), request);
				
				//pobranie subgroups
				getSubgroupsBySemesterID(ContextSettings.getSemesterID(), request);
				
				//pobranie calendarDays
				getCalendarDaysBySemesterID(ContextSettings.getSemesterID(), request);
				
				//pobranie subjectEvents
				getSubjectEventsBySemesterID(ContextSettings.getSemesterID(), request);
				
				//pobranie preferences
				getPreferencesBySemesterID(ContextSettings.getSemesterID(), request);
			}
		});
		
		request.setOnSuccessCmd(new Command() {
			public void execute() {
				Planner.get().getSchedulesList().reloadBranchWithGroupSchedules();
				Planner.get().getSchedulesList().reloadBranchWithLecturersSchedules();
				Planner.get().getSchedulesList().reloadBranchWithRoomsSchedules();
				Planner.get().hideLoadingMessage();
				
				if (ContextSettings.isAdminUserSignedIn()) {
					SchedulesList.generateReports();
				}
			}
		});
		
		PCompositeRequestBuilder builder = new PCompositeRequestBuilder();
		builder.setRequest(request);
		builder.makeAllCalls();

//		//LecturersSchedules
//		MultiRequest mReqLecturers = new MultiRequest(2);
	}
	
	
	/**
	 * Informuje, czy w Cache sa wszystkie potrzebne dane do wygenerowania semestru. 
	 * @return
	 */
	public static boolean containsAllSemesterData() {
		if (studiesTypes.size() == 0) {
			return false;
		}
		if (semesterTypes.size() == 0) {
			return false;
		}

		return true;
	}
	
	

	
	
	
	//pobiera z cache	
	public static CSSubjectEventDTO[] getAllSubjectEvents() {
		CSSubjectEventDTO[] result = new CSSubjectEventDTO[subjectEvents.size()];
		
		int i=0;
		for (Iterator<CSSubjectEventDTO> it = subjectEvents.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//pobiera z cache subjectEventy ALE z ustawionym calendarDay	
	public static CSSubjectEventDTO[] getAllSubjectEventsWithSetCalendarDay() {
		List<CSSubjectEventDTO> result = new ArrayList<CSSubjectEventDTO>();
		
		for (Iterator<CSSubjectEventDTO> it = subjectEvents.values().iterator(); it.hasNext();) {
			CSSubjectEventDTO se = (CSSubjectEventDTO) it.next();
			if (se.getCalendarDayID() > 0) {
				result.add(se);
			}
		}
		
		CSSubjectEventDTO[] resultA = (CSSubjectEventDTO[]) result.toArray(new CSSubjectEventDTO[0]); 
		return resultA;
	}
	
	//zassysa do cache
	private static void getSubjectEvents() {
		AsyncCallback<CSSubjectEventDTO[]> callback = new AsyncCallback<CSSubjectEventDTO[]>() {
			public void onSuccess(CSSubjectEventDTO[] ses) {
				for (int i = 0; i < ses.length; i++) {
					subjectEvents.put(new Long(ses[i].getId()), ses[i]);
				}
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getSubjectEvents(callback);
	}
	
	
	
	public static CSSubjectEventDTO getCSSubjectEventDTOByID(long id) {
		CSSubjectEventDTO result = new CSSubjectEventDTO();
		CSSubjectEventDTO dto = (CSSubjectEventDTO)subjectEvents.get(new Long (id));

		result.setCalendarDayID(dto.getCalendarDayID());
		result.setDuration(dto.getDuration());
		result.setEventSort(dto.getEventSort());
		result.setLecturerID(dto.getLecturerID());
		result.setRoomID(dto.getRoomID());
		result.setStartTime(dto.getStartTime());
		result.setSubgroupID(dto.getSubgroupID());
		result.setSubjectID(dto.getSubjectID());

		return result;
	}
	
	
	public static void saveOrUpdateCSSubjectEvent(CSSubjectEventDTO csSE) {
//		CSSubjectEventDTO result = new CSSubjectEventDTO();
		CSSubjectEventDTO dto = (CSSubjectEventDTO)subjectEvents.get(new Long (csSE.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSSubjectEventDTO(csSE.getId(), csSE.getEventSort(), csSE.getSubjectID(), csSE.getRoomID(), csSE.getSubgroupID(),
					csSE.getLecturerID(), csSE.getCalendarDayID(),
					csSE.getGroupID(), csSE.getSemesterID(),
					csSE.getStartTime(), csSE.getDuration());
			subjectEvents.put(new Long(csSE.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setCalendarDayID(csSE.getCalendarDayID());
			dto.setDuration(csSE.getDuration());
			dto.setEventSort(csSE.getEventSort());
			dto.setLecturerID(csSE.getLecturerID());
			dto.setRoomID(csSE.getRoomID());
			dto.setStartTime(csSE.getStartTime());
			dto.setSubgroupID(csSE.getSubgroupID());
			dto.setSubjectID(csSE.getSubjectID());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csSE
	 */
	public static void removeCSSubjectEvent(CSSubjectEventDTO csSE) {
		subjectEvents.remove(new Long(csSE.getId()));
		
//		CSSubjectEventDTO dto = (CSSubjectEventDTO)subjectEvents.get(new Long (csSE.getId()));
	}
	
	//zassysa do cache subjectEventy z danego semestru
	private static void getSubjectEventsBySemesterID(long semesterID, final PCompositeRequest request) {
		subjectEvents.clear();
		AsyncCallback<CSSubjectEventDTO[]> callback = new AsyncCallback<CSSubjectEventDTO[]>() {
			public void onSuccess(CSSubjectEventDTO[] ses) {
				if (ses != null) {
					for (int i = 0; i < ses.length; i++) {
						subjectEvents.put(new Long(ses[i].getId()), ses[i]);
					}
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getCSSubjectEventsBySemesterID(new Long(semesterID), callback);
	}
	
	//pobiera z cache subject eventy o wskazanym group id	
	public static CSSubjectEventDTO[] getSubjectEventsByGroupID(long groupID) {
		List<CSSubjectEventDTO> result = new ArrayList<CSSubjectEventDTO>();
		
		for (Iterator<CSSubjectEventDTO> it = subjectEvents.values().iterator(); it.hasNext();) {
			CSSubjectEventDTO se = (CSSubjectEventDTO) it.next();
			if (se.getGroupID() == groupID) {
				result.add(se);
			}
		}
		
		CSSubjectEventDTO[] resultA = (CSSubjectEventDTO[]) result.toArray(new CSSubjectEventDTO[0]); 
		return resultA;
	}

	//pobiera z cache subject eventy o wskazanym room id	
	public static CSSubjectEventDTO[] getSubjectEventsByRoomID(long roomID) {
		List<CSSubjectEventDTO> result = new ArrayList<CSSubjectEventDTO>();
		
		for (Iterator<CSSubjectEventDTO> it = subjectEvents.values().iterator(); it.hasNext();) {
			CSSubjectEventDTO se = (CSSubjectEventDTO) it.next();
			if (se.getRoomID() == roomID) {
				result.add(se);
			}
		}
		
		CSSubjectEventDTO[] resultA = (CSSubjectEventDTO[]) result.toArray(new CSSubjectEventDTO[0]); 
		return resultA;
	}
	
	//pobiera z cache subject eventy o wskazanym lecturer id	
	public static CSSubjectEventDTO[] getSubjectEventsByLecturerID(long lecturerID) {
		List<CSSubjectEventDTO> result = new ArrayList<CSSubjectEventDTO>();
		
		for (Iterator<CSSubjectEventDTO> it = subjectEvents.values().iterator(); it.hasNext();) {
			CSSubjectEventDTO se = (CSSubjectEventDTO) it.next();
			if (se.getLecturerID() == lecturerID) {
				result.add(se);
			}
		}
		
		CSSubjectEventDTO[] resultA = (CSSubjectEventDTO[]) result.toArray(new CSSubjectEventDTO[0]); 
		return resultA;
	}
	
	
	
	
	
	//pobiera z cache	
	public static CSSubgroupDTO[] getAllSubgroups(){
		CSSubgroupDTO[] result = new CSSubgroupDTO[subgroups.size()];
		
		int i=0;
		for (Iterator<CSSubgroupDTO> it = subgroups.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
//	//zassysa do cache
//	private static void getSubgroups() {
//		AsyncCallback<CSSubgroupDTO[]> callback = new AsyncCallback<CSSubgroupDTO[]>() {
//			public void onSuccess(CSSubgroupDTO[] sgs) {
//				for (int i = 0; i < sgs.length; i++) {
//					subgroups.put(new Long(sgs[i].getId()), sgs[i]);
//				}
//			}
//
//			public void onFailure(Throwable caught) {
//				Window.alert("ERROR => " + caught);
//			}
//		};
//
//		ServiceHolder.get().getSubgroups(callback);
//	}
	
	public static CSSubgroupDTO getCSSubgroupDTOByID(long id) {
		
//		CSSubgroupDTO result = new CSSubgroupDTO();
		CSSubgroupDTO dto = (CSSubgroupDTO)subgroups.get(new Long (id));
		
////		Planner.log("Cache.getCSSubgroupDTOByID: XXXXXXXXXXXXXXXXXXXXXXXXXX" + "" + dto);
//		if (dto != null) {
//			result.setId(dto.getId());
//			result.setName(dto.getName());
//			result.setStudentsNumber(dto.getStudentsNumber());
//			result.setSubgroupTypeID(dto.getSubgroupTypeID());
//			result.setGroupID(dto.getGroupID());
//		} else {
//			Planner.log("Cache.getCSSubgroupDTOByID: " + "NIE ZNALAZLEM SUBGROUP O PODANYM ID");
//		}
		return dto;
//		return result;
	}
	
	
	public static void saveOrUpdateCSSubgroup(CSSubgroupDTO csS) {
//		CSLecturerDTO result = new CSLecturerDTO();
		CSSubgroupDTO dto = (CSSubgroupDTO)subgroups.get(new Long (csS.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSSubgroupDTO(csS.getId(), csS.getSubgroupTypeID(), csS.getGroupID(), csS.getName(), csS.getStudentsNumber());
			subgroups.put(new Long(csS.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setSubgroupTypeID(csS.getSubgroupTypeID());
			dto.setGroupID(csS.getGroupID());
			dto.setName(csS.getName());
			dto.setStudentsNumber(csS.getStudentsNumber());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csS
	 */
	public static void removeCSSubgroup(CSSubgroupDTO csS) {
		subgroups.remove(new Long(csS.getId()));
		
//		CSSubgroupDTO dto = (CSSubgroupDTO)subgroups.get(new Long (csS.getId()));
	}
	
	
	
	//pobiera z cache podgrupy grupy o wskazanym id	
	public static CSSubgroupDTO[] getSubgroupsByGroupID(long groupID) {
		//CSSubgroupDTO[] result = new CSSubgroupDTO[subgroups.size()];
		List<CSSubgroupDTO> result = new ArrayList<CSSubgroupDTO>();
		
		for (Iterator<CSSubgroupDTO> it = subgroups.values().iterator(); it.hasNext();) {
			CSSubgroupDTO sg = (CSSubgroupDTO) it.next();
			if (sg.getGroupID() == groupID) {
				result.add(sg);
			}
		}
		
		CSSubgroupDTO[] resultA = (CSSubgroupDTO[]) result.toArray(new CSSubgroupDTO[0]); 
		return resultA;
	}
	
	
	
	
	//zassysa do cache podgrupy z danego semestru
	private static void getSubgroupsBySemesterID(long semesterID, final PCompositeRequest request) {
		subgroups.clear();
		AsyncCallback<CSSubgroupDTO[]> callback = new AsyncCallback<CSSubgroupDTO[]>() {
			public void onSuccess(CSSubgroupDTO[] sgs) {
				if (sgs != null) {
					for (int i = 0; i < sgs.length; i++) {
						subgroups.put(new Long(sgs[i].getId()), sgs[i]);
					}
				} else {
					Planner.log("Cache.getSubgroupsBySemesterID.onSuccess: " + "zwrocono 0 subgroups");
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getSubgroupsBySemesterID(new Long(semesterID), callback);
	}
	
	public int getSubgroupsCount() {
		return subgroups.size();
	}
	
	//pobiera z cache	
	public static CSGroupDTO[] getAllGroups(){
		CSGroupDTO[] result = new CSGroupDTO[groups.size()];
		
		int i=0;
		for (Iterator<CSGroupDTO> it = groups.values().iterator(); it.hasNext();) {
			CSGroupDTO g = (CSGroupDTO) it.next();
			result[i++] = g;
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getGroups() {
		AsyncCallback<CSGroupDTO[]> callback = new AsyncCallback<CSGroupDTO[]>() {
			public void onSuccess(CSGroupDTO[] gs) {
				for (int i = 0; i < gs.length; i++) {
					groups.put(new Long(gs[i].getId()), gs[i]);
				}
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getGroups(callback);
	}
	
	//zassysa do cache grupy z danego semestru
	private static void getGroupsBySemesterID(long semesterID, final PCompositeRequest request) {
		groups.clear();
		AsyncCallback<CSGroupDTO[]> callback = new AsyncCallback<CSGroupDTO[]>() {
			public void onSuccess(CSGroupDTO[] gs) {
				for (int i = 0; i < gs.length; i++) {
					groups.put(new Long(gs[i].getId()), gs[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getGroupsBySemesterID(new Long(semesterID), callback);
	}
	
	public static CSGroupDTO getCSGroupDTOByID(long id) {
		CSGroupDTO result = new CSGroupDTO();
		CSGroupDTO dto = (CSGroupDTO)groups.get(new Long (id));
		
		if (dto != null) {
			result.setId(dto.getId());
			result.setName(dto.getName());
			result.setSemestersYearGroupID(dto.getSemestersYearGroupID());
			result.setStudentsNumber(dto.getStudentsNumber());
			result.setScheduleProgress(dto.getScheduleProgress());
		} else {
			Planner.log("Cache.getCSGroupDTOByID: " + "NIE ZNALAZLEM GROUP O PODANYM ID");
		}
		
		return result;
	}
	
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csG
	 */
	public static void removeCSGroup(CSGroupDTO csG) {
		groups.remove(new Long(csG.getId()));
		
//		CSLecturerDTO dto = (CSLecturerDTO)lecturers.get(new Long (csG.getId()));
	}
	
	
	public static void saveOrUpdateCSGroup(CSGroupDTO csG) {
//		CSLecturerDTO result = new CSLecturerDTO();
		CSGroupDTO dto = (CSGroupDTO)groups.get(new Long (csG.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSGroupDTO(csG.getId(), csG.getSemestersYearGroupID(), csG.getName(), csG.getStudentsNumber(), csG.getScheduleProgress());
			groups.put(new Long(csG.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setSemestersYearGroupID(csG.getSemestersYearGroupID());
			dto.setName(csG.getName());
			dto.setStudentsNumber(csG.getStudentsNumber());
			dto.setScheduleProgress(csG.getScheduleProgress());
		}
	}

	public int getGroupsCount() {
		return groups.size();
	}
	
	//pobiera z cache
	public static CSSemestersYearGroupsDTO[] getAllSemestersYearGroups(){
		CSSemestersYearGroupsDTO[] result = new CSSemestersYearGroupsDTO[semestersYearGroups.size()];
		
		int i=0;
		for (Iterator<CSSemestersYearGroupsDTO> it = semestersYearGroups.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getSemestersYearGroups() {
		AsyncCallback<CSSemestersYearGroupsDTO[]> callback = new AsyncCallback<CSSemestersYearGroupsDTO[]>() {
			public void onSuccess(CSSemestersYearGroupsDTO[] sygs) {
				for (int i = 0; i < sygs.length; i++) {
					semestersYearGroups.put(new Long(sygs[i].getId()), sygs[i]);
				}
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getSemestersYearGroups(callback);
	}
	
	//zassysa do cache
	private static void getSemestersYearGroupsBySemesterID(long semesterID, final PCompositeRequest request) {
		semestersYearGroups.clear();
		AsyncCallback<CSSemestersYearGroupsDTO[]> callback = new AsyncCallback<CSSemestersYearGroupsDTO[]>() {
			public void onSuccess(CSSemestersYearGroupsDTO[] sygs) {
				for (int i = 0; i < sygs.length; i++) {
					semestersYearGroups.put(new Long(sygs[i].getId()), sygs[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getCSSemestersYearGroupsBySemesterID(new Long(semesterID), callback);
	}
	
	

	public static CSSemestersYearGroupsDTO getCSSemestersYearGroupsDTOByID(long id) {
//		CSSemestersYearGroupsDTO result = new CSSemestersYearGroupsDTO();
		CSSemestersYearGroupsDTO dto = (CSSemestersYearGroupsDTO)semestersYearGroups.get(new Long(id));
		
//		result.setId(dto.getId());
//		result.setSemesterID(dto.getSemester().getId());
//		result.setStudentsNumber(dto.getStudentsNumber());
//		result.setYearGroupNameID(dto.getYearGroupName().getId());
				
		return dto;
	}
	
	
	public static void saveOrUpdateCSSemestersYearGroups(CSSemestersYearGroupsDTO csSYG) {
//		CSLecturerDTO result = new CSLecturerDTO();
		CSSemestersYearGroupsDTO dto = (CSSemestersYearGroupsDTO)semestersYearGroups.get(new Long (csSYG.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSSemestersYearGroupsDTO(csSYG.getId(), csSYG.getSemesterID(), csSYG.getYearGroupNameID(), csSYG.getStudentsNumber());
			semestersYearGroups.put(new Long(csSYG.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setYearGroupNameID(csSYG.getYearGroupNameID());
			dto.setSemesterID(csSYG.getSemesterID());
			dto.setStudentsNumber(csSYG.getStudentsNumber());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csSYG
	 */
	public static void removeCSSemestersYearGroups(CSSemestersYearGroupsDTO csSYG) {
		semestersYearGroups.remove(new Long(csSYG.getId()));
		
		//CSSemestersYearGroupsDTO dto = (CSSemestersYearGroupsDTO)semestersYearGroups.get(new Long (csSYG.getId()));
	}

	/**
	 * Zwraca liczbe wczytanych do cache obiektow.
	 * @return
	 */
	public static int getLoadedSemesterYearGroupsCount() {
		return semestersYearGroups.size();
	}
	
	//pobiera z cache
	public static CSYearGroupNameDTO[] getAllYearGroupNames(){
		CSYearGroupNameDTO[] result = new CSYearGroupNameDTO[yearGroupNames.size()];
		
		int i=0;
		for (Iterator<CSYearGroupNameDTO> it = yearGroupNames.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		return result;
	}
	
	//zassysa do cache
	private static void getYearGroupNames(final PCompositeRequest request) {
		AsyncCallback<CSYearGroupNameDTO[]> callback = new AsyncCallback<CSYearGroupNameDTO[]>() {
			public void onSuccess(CSYearGroupNameDTO[] ygn) {
				for (int i = 0; i < ygn.length; i++) {
					yearGroupNames.put(new Long(ygn[i].getId()), ygn[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getYearGroupNames(callback);
	}
	
	public static CSYearGroupNameDTO getCSYearGroupNameDTOByID(long id) {
		CSYearGroupNameDTO result = new CSYearGroupNameDTO();
		
		CSYearGroupNameDTO dto = (CSYearGroupNameDTO)yearGroupNames.get(new Long(id));
		
		result.setId(dto.getId());
		result.setName(dto.getName());
		
		return result;
	}
	
	public static void saveOrUpdateCSYearGroupName(CSYearGroupNameDTO csYGN) {
		CSYearGroupNameDTO dto = (CSYearGroupNameDTO)yearGroupNames.get(new Long (csYGN.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSYearGroupNameDTO(csYGN.getId(), csYGN.getName());
			yearGroupNames.put(new Long(csYGN.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setName(csYGN.getName());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csYGN
	 */
	public static void removeCSYearGroupName(CSYearGroupNameDTO csYGN) {
		yearGroupNames.remove(new Long(csYGN.getId()));
		
		//CSAcademicTitleDTO dto = (CSAcademicTitleDTO)academicTitles.get(new Long (csAT.getId()));
	}

	
	
	
	//pobiera z cache
	public static CSCalendarDayDTO[] getAllCalendarDays(){
		CSCalendarDayDTO[] result = new CSCalendarDayDTO[calendarDays.size()];
		
		int i=0;
		for (Iterator<CSCalendarDayDTO> it = calendarDays.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
//	//zassysa do cache wszystkie calendarDays
//	private static void getCalendarDays() {
//		AsyncCallback<CSCalendarDayDTO[]> callback = new AsyncCallback<CSCalendarDayDTO[]>() {
//			public void onSuccess(CSCalendarDayDTO[] cds) {
//				for (int i = 0; i < cds.length; i++) {
//					calendarDays.put(new Long(cds[i].getId()), cds[i]);
//				}
//			}
//
//			public void onFailure(Throwable caught) {
//				Window.alert("ERROR => " + caught);
//			}
//		};
//
//		ServiceHolder.get().getCalendarDays(callback);
//	}
	

	public static CSCalendarDayDTO getCSCalendarDayDTOByID(long id) {
		CSCalendarDayDTO result = new CSCalendarDayDTO();
		CSCalendarDayDTO dto = (CSCalendarDayDTO)calendarDays.get(new Long (id));
		
		result.setDayLabel(dto.getDayLabel());
		result.setDisplayOrder(dto.getDisplayOrder());
		result.setId(dto.getId());
		result.setSemesterID(dto.getSemesterID());
		
		return result;
	}
	
	public static void saveOrUpdateCSCalendarDay(CSCalendarDayDTO csCD) {
		CSCalendarDayDTO dto = (CSCalendarDayDTO)calendarDays.get(new Long (csCD.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSCalendarDayDTO(csCD.getId(), csCD.getSemesterID(), csCD.getDayLabel(), csCD.getDisplayOrder(), csCD.isSunday());
			calendarDays.put(new Long(csCD.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setDayLabel(csCD.getDayLabel());
			dto.setDisplayOrder(csCD.getDisplayOrder());
			dto.setSemesterID(csCD.getSemesterID());
			dto.setSunday(csCD.isSunday());
		}
	}

	/**
	 * Usuwa z cache'u rekord.
	 * @param csCD
	 */
	public static void removeCSCalendarDay(CSCalendarDayDTO csCD) {
		calendarDays.remove(new Long(csCD.getId()));
	}

	
	
//	//pobiera z cache calendarDays o wskazanym semesterID	
//	public static CSCalendarDayDTO[] getCalendarDaysBySemesterID(long semesterID) {
//		//CSSubgroupDTO[] result = new CSSubgroupDTO[subgroups.size()];
//		List result = new ArrayList();
//		
//		int i=0;
//		for (Iterator it = calendarDays.values().iterator(); it.hasNext();) {
//			CSCalendarDayDTO cd = (CSCalendarDayDTO) it.next();
//			if (cd.getSemesterID() == semesterID) {
//				result.add(cd);
//			}
//		}
//		
//		CSCalendarDayDTO[] resultA = (CSCalendarDayDTO[]) result.toArray(new CSCalendarDayDTO[0]); 
//		return resultA;
//	}
	
	
	//zassysa do cache grupy z danego semestru
	private static void getCalendarDaysBySemesterID(long semesterID, final PCompositeRequest request) {
		calendarDays.clear();
		AsyncCallback<CSCalendarDayDTO[]> callback = new AsyncCallback<CSCalendarDayDTO[]>() {
			public void onSuccess(CSCalendarDayDTO[] cds) {
				for (int i = 0; i < cds.length; i++) {
					calendarDays.put(new Long(cds[i].getId()), cds[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getCSCalendarDaysBySemesterID(new Long(semesterID), callback);
	}

	
	
	
	//pobiera z cache
	public static CSSemesterDTO[] getAllSemesters(){
		CSSemesterDTO[] result = new CSSemesterDTO[semesters.size()];
		
		int i=0;
		for (Iterator<CSSemesterDTO> it = semesters.values().iterator(); it.hasNext();) {
			CSSemesterDTO s = (CSSemesterDTO) it.next();
			result[i++] = s;
		}
		
		return result;
	}
	
	
	//zassysa do cache
	private static void getSemesters(final PCompositeRequest request) {
		AsyncCallback<CSSemesterDTO[]> callback = new AsyncCallback<CSSemesterDTO[]>() {
			public void onSuccess(CSSemesterDTO[] ss) {
				for (int i = 0; i < ss.length; i++) {
					semesters.put(new Long(ss[i].getId()), ss[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getCSSemesters(callback);
	}
	
	public static CSSemesterDTO getCSSemesterDTOByID(long id) {
//		CSSemesterDTO result = new CSSemesterDTO();
		CSSemesterDTO dto = (CSSemesterDTO)semesters.get(new Long (id));
		
		return dto;
	}
	
	public static void saveOrUpdateCSSemester(CSSemesterDTO csS) {
//		CSLecturerDTO result = new CSLecturerDTO();
		CSSemesterDTO dto = (CSSemesterDTO)semesters.get(new Long (csS.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSSemesterDTO(csS.getId(), csS.getStudiesTypeID(), csS.getSemesterTypeID(), csS.getYearNumber(), csS.isVisibleForOrdinaryUsers());
			semesters.put(new Long(csS.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setStudiesTypeID(csS.getStudiesTypeID());
			dto.setSemesterTypeID(csS.getSemesterTypeID());
			dto.setYearNumber(csS.getYearNumber());
			dto.setVisibleForOrdinaryUsers(csS.isVisibleForOrdinaryUsers());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csS
	 */
	public static void removeCSSemester(CSSemesterDTO csS) {
		semesters.remove(new Long(csS.getId()));
		
//		CSSemesterDTO dto = (CSSemesterDTO)semesters.get(new Long (csS.getId()));
	}
	
	/**
	 * Zwraca liczbe wczytanych do cache obiektow.
	 * @return
	 */
	public static int getLoadedSemestersCount() {
		return semesters.size();
	}

	

	
	
//	//pobiera z cache
//	public static CSYearNumberDTO[] getAllYearNumbers() {
//		CSYearNumberDTO[] result = new CSYearNumberDTO[yearNumbers.size()];
//		
//		int i=0;
//		for (Iterator it = yearNumbers.values().iterator(); it.hasNext();) {
//			CSYearNumberDTO yn = (CSYearNumberDTO) it.next();
//			result[i++] = yn;
//		}
//		
//		return result;
//	}
	
//	//zassysa do cache
//	private static void getYearNumbers(final PCompositeRequest request) {
//		AsyncCallback callback = new AsyncCallback() {
//			public void onSuccess(Object result) {
//				CSYearNumberDTO[] yns = (CSYearNumberDTO[])result;
//				for (int i = 0; i < yns.length; i++) {
//					yearNumbers.put(new Long(yns[i].getId()), yns[i]);
//				}
//				request.runOnSuccessCmd();
//			}
//
//			public void onFailure(Throwable caught) {
//				Window.alert("ERROR => " + caught);
//			}
//		};
//
//		ServiceHolder.get().getYearNumbers(callback);
//	}
	

	
	//pobiera z cache
	public static CSSemesterTypeDTO[] getAllSemesterTypes(){
		CSSemesterTypeDTO[] result = new CSSemesterTypeDTO[semesterTypes.size()];
		
		int i=0;
		for (Iterator<CSSemesterTypeDTO> it = semesterTypes.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getSemesterTypes(final PCompositeRequest request) {
		AsyncCallback<CSSemesterTypeDTO[]> callback = new AsyncCallback<CSSemesterTypeDTO[]>() {
			public void onSuccess(CSSemesterTypeDTO[] sts) {
				for (int i = 0; i < sts.length; i++) {
					semesterTypes.put(new Long(sts[i].getId()), sts[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getSemesterTypes(callback);
	}
	//TODO uproscic metody
	public static CSSemesterTypeDTO getCSSemesterTypeDTOByID(long id) {
		CSSemesterTypeDTO result = new CSSemesterTypeDTO();
		CSSemesterTypeDTO dto = (CSSemesterTypeDTO)semesterTypes.get(new Long(id));
		
		result.setId(dto.getId());
		result.setName(dto.getName());
		
		return result;
	}
	
	public static CSStudiesTypeDTO getCSStudiesTypeDTOByID(long id) {
		CSStudiesTypeDTO result = new CSStudiesTypeDTO();
		CSStudiesTypeDTO dto = (CSStudiesTypeDTO)studiesTypes.get(new Long(id));
		
		result.setId(dto.getId());
		result.setName(dto.getName());
		
		return result;
	}
	
	//pobiera z cache
	public static CSStudiesTypeDTO[] getAllStudiesTypes(){
		CSStudiesTypeDTO[] result = new CSStudiesTypeDTO[studiesTypes.size()];
		
		int i=0;
		for (Iterator<CSStudiesTypeDTO> it = studiesTypes.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getStudiesTypes(final PCompositeRequest request) {
		AsyncCallback<CSStudiesTypeDTO[]> callback = new AsyncCallback<CSStudiesTypeDTO[]>() {
			public void onSuccess(CSStudiesTypeDTO[] sts) {
				for (int i = 0; i < sts.length; i++) {
					studiesTypes.put(new Long(sts[i].getId()), sts[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getStudiesTypes(callback);
	}
	
	//pobiera z cache
	public static CSSubgroupTypeDTO[] getAllSubgroupTypes(){
		CSSubgroupTypeDTO[] result = new CSSubgroupTypeDTO[subgroupTypes.size()];
		
		int i=0;
		for (Iterator<CSSubgroupTypeDTO> it = subgroupTypes.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getSubgroupTypes(final PCompositeRequest request) {
		AsyncCallback<CSSubgroupTypeDTO[]> callback = new AsyncCallback<CSSubgroupTypeDTO[]>() {
			public void onSuccess(CSSubgroupTypeDTO[] sts) {
				for (int i = 0; i < sts.length; i++) {
					subgroupTypes.put(new Long(sts[i].getId()), sts[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getSubgroupTypes(callback);
	}
	
	
	public static CSSubgroupTypeDTO getCSSubgroupTypeDTOByID(long id) {
		CSSubgroupTypeDTO result = new CSSubgroupTypeDTO();
		CSSubgroupTypeDTO dto = (CSSubgroupTypeDTO)subgroupTypes.get(new Long(id));
		
		if (dto != null) {
			result.setId(dto.getId());
			result.setName(dto.getName());
		} else {
			result.setId(id);
			result.setName("(" + id + ") subgroup type not found in cache");
		}
		
		return result;
	}
	
	public static void saveOrUpdateCSSubgroupType(CSSubgroupTypeDTO csST) {
		CSSubgroupTypeDTO dto = (CSSubgroupTypeDTO)subgroupTypes.get(new Long (csST.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSSubgroupTypeDTO(csST.getId(), csST.getName());
			subgroupTypes.put(new Long(csST.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setName(csST.getName());
		}
	}
	
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csST
	 */
	public static void removeCSSubgroupType(CSSubgroupTypeDTO csST) {
		subgroupTypes.remove(new Long(csST.getId()));
	}


	
	//pobiera z cache
	public static CSSubjectDTO[] getAllSubjects(){
		CSSubjectDTO[] result = new CSSubjectDTO[subjects.size()];
		
		int i=0;
		for (Iterator<CSSubjectDTO> it = subjects.values().iterator(); it.hasNext();) {
			CSSubjectDTO s = (CSSubjectDTO) it.next();
			result[i++] = s;
		}
		
		return result;
	}
	

	//zassysa do cache
	private static void getSubjects(final PCompositeRequest request) {
		
		AsyncCallback<CSSubjectDTO[]> callback = new AsyncCallback<CSSubjectDTO[]>() {
			public void onSuccess(CSSubjectDTO[] ss) {
				for (int i = 0; i < ss.length; i++) {
					subjects.put(new Long(ss[i].getId()), ss[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getSubjects(callback);
	}
	
	public static CSSubjectDTO getCSSubjectDTOByID(long id) {
		
		CSSubjectDTO result = new CSSubjectDTO();
		CSSubjectDTO dto = (CSSubjectDTO)subjects.get(new Long (id));
		
		result.setId(dto.getId());
		result.setSubjectNameID(dto.getSubjectNameID());
		result.setSubjectTypeID(dto.getSubjectTypeID());
		
		return result;
	}
	
	
	public static void saveOrUpdateCSSubject(CSSubjectDTO csS) {
		CSSubjectDTO dto = (CSSubjectDTO)subjects.get(new Long (csS.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSSubjectDTO(csS.getId(), csS.getSubjectTypeID(), csS.getSubjectNameID());
			subjects.put(new Long(csS.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setSubjectTypeID(csS.getSubjectTypeID());
			dto.setSubjectNameID(csS.getSubjectNameID());
		}
	}

	/**
	 * Usuwa z cache'u rekord.
	 * @param csS
	 */
	public static void removeCSSubject(CSSubjectDTO csS) {
		subjects.remove(new Long(csS.getId()));
	}

	
	
	//pobiera z cache
	public static CSSubjectNameDTO[] getAllSubjectNames(){
		CSSubjectNameDTO[] result = new CSSubjectNameDTO[subjectNames.size()];
		
		int i=0;
		for (Iterator<CSSubjectNameDTO> it = subjectNames.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getSubjectNames(final PCompositeRequest request) {
		
		AsyncCallback<CSSubjectNameDTO[]> callback = new AsyncCallback<CSSubjectNameDTO[]>() {
			public void onSuccess(CSSubjectNameDTO[] sns) {
				for (int i = 0; i < sns.length; i++) {
					subjectNames.put(new Long(sns[i].getId()), sns[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getSubjectNames(callback);
	}
	
	public static CSSubjectNameDTO getCSSubjectNameDTOByID(long id) {
		CSSubjectNameDTO result = new CSSubjectNameDTO();
		CSSubjectNameDTO dto = (CSSubjectNameDTO)subjectNames.get(new Long(id));

		result.setId(dto.getId());
		result.setName(dto.getName());
		result.setSymbol(dto.getSymbol());
		
		return result;
	}
	
	public static void saveOrUpdateCSSubjectName(CSSubjectNameDTO csSN) {
		CSSubjectNameDTO dto = (CSSubjectNameDTO)subjectNames.get(new Long (csSN.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSSubjectNameDTO(csSN.getId(), csSN.getName(), csSN.getSymbol());
			subjectNames.put(new Long(csSN.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setName(csSN.getName());
			dto.setSymbol(csSN.getSymbol());
		}
	}
	
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csAT
	 */
	public static void removeCSSubjectName(CSSubjectNameDTO csSN) {
		subjectNames.remove(new Long(csSN.getId()));
	}

	
	//pobiera z cache
	public static CSSubjectTypeDTO[] getAllSubjectTypes(){
		CSSubjectTypeDTO[] result = new CSSubjectTypeDTO[subjectTypes.size()];
		
		int i=0;
		for (Iterator<CSSubjectTypeDTO> it = subjectTypes.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getSubjectTypes(final PCompositeRequest request) {
		
		AsyncCallback<CSSubjectTypeDTO[]> callback = new AsyncCallback<CSSubjectTypeDTO[]>() {
			public void onSuccess(CSSubjectTypeDTO[] sts) {
				for (int i = 0; i < sts.length; i++) {
					subjectTypes.put(new Long(sts[i].getId()), sts[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getSubjectTypes(callback);
	}
	
	public static CSSubjectTypeDTO getCSSubjectTypeDTOByID(long id) {
		
		CSSubjectTypeDTO result = new CSSubjectTypeDTO();
		CSSubjectTypeDTO dto = (CSSubjectTypeDTO)subjectTypes.get(new Long(id));

		result.setId(dto.getId());
		result.setName(dto.getName());
		result.setInitial(dto.getInitial());
		
		return result;
	}
	
	public static void saveOrUpdateCSSubjectType(CSSubjectTypeDTO csST) {
		CSSubjectTypeDTO dto = (CSSubjectTypeDTO)subjectTypes.get(new Long (csST.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSSubjectTypeDTO(csST.getId(), csST.getName(), csST.getInitial());
			subjectTypes.put(new Long(csST.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setName(csST.getName());
			dto.setInitial(csST.getInitial());
		}
	}
	
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csST
	 */
	public static void removeCSSubjectType(CSSubjectTypeDTO csST) {
		subjectTypes.remove(new Long(csST.getId()));
	}
	
	//pobiera z cache
	public static CSRoomDTO[] getAllRooms(){
		CSRoomDTO[] result = new CSRoomDTO[rooms.size()];
		
		int i=0;
		for (Iterator<CSRoomDTO> it = rooms.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getRooms(final PCompositeRequest request) {
		
		AsyncCallback<CSRoomDTO[]> callback = new AsyncCallback<CSRoomDTO[]>() {
			public void onSuccess(CSRoomDTO[] r) {
				for (int i = 0; i < r.length; i++) {
					rooms.put(new Long(r[i].getId()), r[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getRooms(callback);
	}
	
	
	public static CSRoomDTO getCSRoomDTOByID(long id) {
//		CSRoomDTO result = new CSRoomDTO();
		CSRoomDTO dto = (CSRoomDTO)rooms.get(new Long(id));

		
		return dto;
		
		
		
//		CSLecturerDTO result = new CSLecturerDTO();
//		CSLecturerDTO dto = (CSLecturerDTO)lecturers.get(new Long (id));
		
//		result.setName(dto.getName());
//		result.setSurname(dto.getSurname());
//		result.setAcademicTitleID(dto.getAcademicTitleID());
//		
//		return result;
	}
	
	public static void saveOrUpdateCSRoom(CSRoomDTO csS) {
		CSRoomDTO dto = (CSRoomDTO)rooms.get(new Long (csS.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSRoomDTO(csS.getId(), csS.getName(), csS.getCapacity(), csS.getBuildingID(), csS.getRoomTypeID());
			rooms.put(new Long(csS.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setName(csS.getName());
			dto.setCapacity(csS.getCapacity());
			dto.setRoomTypeID(csS.getRoomTypeID());
			dto.setBuildingID(csS.getBuildingID());
		}
	}

	/**
	 * Usuwa z cache'u rekord.
	 * @param csR
	 */
	public static void removeCSRoom(CSRoomDTO csR) {
		rooms.remove(new Long(csR.getId()));
	}
	
	public int getRoomsCount() {
		return rooms.size();
	}
	
	
	//pobiera z cache
	public static CSRoomTypeDTO[] getAllRoomTypes(){
		CSRoomTypeDTO[] result = new CSRoomTypeDTO[roomTypes.size()];
		
		int i=0;
		for (Iterator<CSRoomTypeDTO> it = roomTypes.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getRoomTypes(final PCompositeRequest request) {
		
		AsyncCallback<CSRoomTypeDTO[]> callback = new AsyncCallback<CSRoomTypeDTO[]>() {
			public void onSuccess(CSRoomTypeDTO[] rts) {
				for (int i = 0; i < rts.length; i++) {
					roomTypes.put(new Long(rts[i].getId()), rts[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getRoomTypes(callback);
	}
	
	
	public static CSRoomTypeDTO getCSRoomTypeDTOByID(long id) {
		CSRoomTypeDTO result = new CSRoomTypeDTO();
		CSRoomTypeDTO dto = (CSRoomTypeDTO)roomTypes.get(new Long (id));
		
		result.setId(dto.getId());
		result.setName(dto.getName());
		
		return result;
	}
	
	public static void saveOrUpdateCSRoomType(CSRoomTypeDTO csRT) {
		CSRoomTypeDTO dto = (CSRoomTypeDTO)roomTypes.get(new Long (csRT.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSRoomTypeDTO(csRT.getId(), csRT.getName());
			roomTypes.put(new Long(csRT.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setName(csRT.getName());
		}
	}
	
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csRT
	 */
	public static void removeCSRoomType(CSRoomTypeDTO csRT) {
		roomTypes.remove(new Long(csRT.getId()));
	}

	
	
	//pobiera z cache
	public static CSBuildingDTO[] getAllBuildings(){
		CSBuildingDTO[] result = new CSBuildingDTO[buildings.size()];
		
		int i=0;
		for (Iterator<CSBuildingDTO> it = buildings.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getBuildings(final PCompositeRequest req) {
		
		AsyncCallback<CSBuildingDTO[]> callback = new AsyncCallback<CSBuildingDTO[]>() {
			public void onSuccess(CSBuildingDTO[] bs) {
				for (int i = 0; i < bs.length; i++) {
					buildings.put(new Long(bs[i].getId()), bs[i]);
				}
				req.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getBuildings(callback);
	}
	
	public static CSBuildingDTO getCSBuildingDTOByID(long id) {
		CSBuildingDTO result = new CSBuildingDTO();
		CSBuildingDTO dto = (CSBuildingDTO)buildings.get(new Long (id));
		
		
		result.setId(dto.getId());
		result.setName(dto.getName());
		result.setSymbol(dto.getSymbol());
		
		return result;
	}
	
	public static void saveOrUpdateCSBuilding(CSBuildingDTO csB) {
		CSBuildingDTO dto = (CSBuildingDTO)buildings.get(new Long (csB.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSBuildingDTO(csB.getId(), csB.getName(), csB.getSymbol());
			buildings.put(new Long(csB.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setName(csB.getName());
			dto.setSymbol(csB.getSymbol());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csB
	 */
	public static void removeCSBuilding(CSBuildingDTO csB) {
		buildings.remove(new Long(csB.getId()));
	}
	
	public int getAcademicTitlesCount() {
		return academicTitles.size();
	}
	
	//pobiera z cache
	public static CSAcademicTitleDTO[] getAllAcademicTitles(){
		CSAcademicTitleDTO[] result = new CSAcademicTitleDTO[academicTitles.size()];
		
		int i=0;
		for (Iterator<CSAcademicTitleDTO> it = academicTitles.values().iterator(); it.hasNext();) {
			CSAcademicTitleDTO at = (CSAcademicTitleDTO) it.next();
			result[i++] = at;
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getAcademicTitles(final PCompositeRequest request) {
		
		AsyncCallback<CSAcademicTitleDTO[]> callback = new AsyncCallback<CSAcademicTitleDTO[]>() {
			public void onSuccess(CSAcademicTitleDTO[] ats) {
				for (int i = 0; i < ats.length; i++) {
					academicTitles.put(new Long(ats[i].getId()), ats[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getAcademicTitles(callback);
	}
	
	
	public static CSAcademicTitleDTO getCSAcademicTitleDTOByID(long id) {
		CSAcademicTitleDTO result = new CSAcademicTitleDTO();
		CSAcademicTitleDTO dto = (CSAcademicTitleDTO)academicTitles.get(new Long (id));
		
		result.setTitle(dto.getTitle());
		
		return result;
	}
	
	public static void saveOrUpdateCSAcademicTitle(CSAcademicTitleDTO csAT) {
		CSAcademicTitleDTO dto = (CSAcademicTitleDTO)academicTitles.get(new Long (csAT.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSAcademicTitleDTO(csAT.getId(), csAT.getTitle());
			academicTitles.put(new Long(csAT.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setTitle(csAT.getTitle());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csAT
	 */
	public static void removeCSAcademicTitle(CSAcademicTitleDTO csAT) {
		academicTitles.remove(new Long(csAT.getId()));
		
		//CSAcademicTitleDTO dto = (CSAcademicTitleDTO)academicTitles.get(new Long (csAT.getId()));
	}
	
	
	//pobiera z cache
	public static CSLecturerDTO[] getAllLecturers() {
		CSLecturerDTO[] result = new CSLecturerDTO[lecturers.size()];
		
		int i=0;
		for (Iterator<CSLecturerDTO> it = lecturers.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	public int getLecturersCount() {
		return lecturers.size();
	}
	
	//zassysa do cache
	private static void getLecturers(final PCompositeRequest request) {
		
		AsyncCallback<CSLecturerDTO[]> callback = new AsyncCallback<CSLecturerDTO[]>() {
			public void onSuccess(CSLecturerDTO[] ls) {
				for (int i = 0; i < ls.length; i++) {
					lecturers.put(new Long(ls[i].getId()), ls[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getLecturers(callback);
	}
	
	public static CSLecturerDTO getCSLecturerDTOByID(long id) {
		CSLecturerDTO result = new CSLecturerDTO();
		CSLecturerDTO dto = (CSLecturerDTO)lecturers.get(new Long (id));
		
		result.setName(dto.getName());
		result.setSurname(dto.getSurname());
		result.setAcademicTitleID(dto.getAcademicTitleID());
		
		return result;
	}
	
	
	public static void saveOrUpdateCSLecturer(CSLecturerDTO csL) {
//		CSLecturerDTO result = new CSLecturerDTO();
		CSLecturerDTO dto = (CSLecturerDTO)lecturers.get(new Long (csL.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSLecturerDTO(csL.getId(), csL.getName(), csL.getSurname(), csL.getAcademicTitleID());
			lecturers.put(new Long(csL.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setAcademicTitleID(csL.getAcademicTitleID());
			dto.setName(csL.getName());
			dto.setSurname(csL.getSurname());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csL
	 */
	public static void removeCSLecturer(CSLecturerDTO csL) {
		lecturers.remove(new Long(csL.getId()));
		
//		CSLecturerDTO dto = (CSLecturerDTO)lecturers.get(new Long (csL.getId()));
	}

	
	

	
	//pobiera z cache
	public static CSPreferenceTypeDTO[] getAllPreferenceTypes() {
		CSPreferenceTypeDTO[] result = new CSPreferenceTypeDTO[preferenceTypes.size()];
		
		int i=0;
		for (Iterator<CSPreferenceTypeDTO> it = preferenceTypes.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getPreferenceTypes(final PCompositeRequest request) {
		
		AsyncCallback<CSPreferenceTypeDTO[]> callback = new AsyncCallback<CSPreferenceTypeDTO[]>() {
			public void onSuccess(CSPreferenceTypeDTO[] pts) {
				for (int i = 0; i < pts.length; i++) {
					preferenceTypes.put(new Long(pts[i].getId()), pts[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getPreferenceTypes(callback);
	}
	
	
	//
	public static CSPreferenceTypeDTO getCSPreferenceTypeDTOByID(long id) {
		CSPreferenceTypeDTO result = new CSPreferenceTypeDTO();
		CSPreferenceTypeDTO dto = (CSPreferenceTypeDTO)preferenceTypes.get(new Long (id));
		
		result.setName(dto.getName());
		result.setColor(dto.getColor());
		
		return result;
	}
	
	public static void saveOrUpdateCSPreferenceType(CSPreferenceTypeDTO csPT) {
		CSPreferenceTypeDTO dto = (CSPreferenceTypeDTO)preferenceTypes.get(new Long (csPT.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSPreferenceTypeDTO(csPT.getId(), csPT.getName(), csPT.getColor());
			preferenceTypes.put(new Long(csPT.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setName(csPT.getName());
			dto.setColor(csPT.getColor());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csPT
	 */
	public static void removeCSPreferenceType(CSPreferenceTypeDTO csPT) {
		preferenceTypes.remove(new Long(csPT.getId()));
		
		//CSAcademicTitleDTO dto = (CSAcademicTitleDTO)academicTitles.get(new Long (csAT.getId()));
	}

	
	
	//pobiera z cache
	public static CSPreferenceDTO[] getAllPreferences() {
		CSPreferenceDTO[] result = new CSPreferenceDTO[preferences.size()];
		
		int i=0;
		for (Iterator<CSPreferenceDTO> it = preferences.values().iterator(); it.hasNext();) {
			result[i++] = it.next();
		}
		
		return result;
	}
	
//	//zassysa do cache
//	private static void getPreferences() {
//		
//		AsyncCallback<CSPreferenceDTO[]> callback = new AsyncCallback<CSPreferenceDTO[]>() {
//			public void onSuccess(CSPreferenceDTO[] ps) {
//				for (int i = 0; i < ps.length; i++) {
//					preferences.put(new Long(ps[i].getId()), ps[i]);
//				}
//			}
//
//			public void onFailure(Throwable caught) {
//				Window.alert("ERROR => " + caught);
//			}
//		};
//
//		ServiceHolder.get().getPreferences(callback);
//	}
	
	//zassysa do cache preferences z danego semestru
	private static void getPreferencesBySemesterID(long semesterID, final PCompositeRequest request) {
		preferences.clear();
		AsyncCallback<CSPreferenceDTO[]> callback = new AsyncCallback<CSPreferenceDTO[]>() {
			public void onSuccess(CSPreferenceDTO[] ps) {
				if (ps != null) {
					for (int i = 0; i < ps.length; i++) {
						preferences.put(new Long(ps[i].getId()), ps[i]);
					}
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getCSPreferencesBySemesterID(new Long(semesterID), callback);
	}

	//pobiera z cache preferences o wskazanym lecturer id	
	public static CSPreferenceDTO[] getPreferencesByLecturerID(long lecturerID) {
		List<CSPreferenceDTO> result = new ArrayList<CSPreferenceDTO>();
		
		for (Iterator<CSPreferenceDTO> it = preferences.values().iterator(); it.hasNext();) {
			CSPreferenceDTO p = (CSPreferenceDTO) it.next();
			if (p.getLecturerID() == lecturerID) {
				result.add(p);
			}
		}
		
		CSPreferenceDTO[] resultA = (CSPreferenceDTO[]) result.toArray(new CSPreferenceDTO[0]); 
		return resultA;
	}

	
	//pobiera z cache	
	public static CSDeclarationDTO[] getAllDeclarations(){
		CSDeclarationDTO[] result = new CSDeclarationDTO[declarations.size()];
		
		int i=0;
		for (Iterator<CSDeclarationDTO> it = declarations.values().iterator(); it.hasNext();) {
			CSDeclarationDTO d = it.next();
			
			CSDeclarationDTO newD = new CSDeclarationDTO(d.getId(), d.getGroupID(), d.getSubgroupTypeID(), d.getSubjectID(), new Integer(d.getDuration()), new Integer(d.getToSchedule()));
//			CSDeclarationDTO newD = new CSDeclarationDTO(d.getId(), d.getGroupID(), d.getSubgroupTypeID(), d.getSubjectID(), new Long(d.getSubgroupsAmount()), new Integer(d.getDuration()), new Integer(d.getToSchedule()));
			result[i++] = newD;
		}
		
		return result;
	}
	
	//zassysa do cache
	private static void getDeclarations() {
		AsyncCallback<CSDeclarationDTO[]> callback = new AsyncCallback<CSDeclarationDTO[]>() {
			public void onSuccess(CSDeclarationDTO[] ds) {
				for (int i = 0; i < ds.length; i++) {
					declarations.put(new Long(ds[i].getId()), ds[i]);
				}
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getDeclarations(callback);
	}
	
	//zassysa do cache grupy z danego semestru
	private static void getDeclarationsBySemesterID(long semesterID, final PCompositeRequest request) {
		declarations.clear();
		AsyncCallback<CSDeclarationDTO[]> callback = new AsyncCallback<CSDeclarationDTO[]>() {
			public void onSuccess(CSDeclarationDTO[] ds) {
				for (int i = 0; i < ds.length; i++) {
					declarations.put(new Long(ds[i].getId()), ds[i]);
				}
				request.runOnSuccessCmd();
			}

			public void onFailure(Throwable caught) {
				Window.alert("ERROR => " + caught);
			}
		};

		ServiceHolder.get().getCSDeclarationsBySemesterID(semesterID, callback);
	}
	
	public static CSDeclarationDTO getCSDeclarationDTOByID(long id) {
		
		CSDeclarationDTO result = new CSDeclarationDTO();
		CSDeclarationDTO dto = (CSDeclarationDTO)declarations.get(new Long (id));
		
		result.setDuration(new Integer(dto.getDuration()));
		result.setGroupID(dto.getGroupID());
		result.setId(dto.getId());
		result.setSubgroupTypeID(dto.getSubgroupTypeID());
		result.setSubjectID(dto.getSubjectID());
		result.setToSchedule(new Integer(dto.getToSchedule()));
		
//////		Planner.log("Cache.getCSDeclarationDTOByID: XXXXXXXXXXXXXXXXXXXXXXXXXX" + "" + dto);
////		if (dto != null) {
////			result.setDuration(duration)
////			result.setId(dto.getId());
////			result.setName(dto.getName());
////			result.setStudentsNumber(dto.getStudentsNumber());
////			result.setSubgroupTypeID(dto.getSubgroupTypeID());
////			result.setGroupID(dto.getGroupID());
////		} else {
////			Planner.log("Cache.getCSDeclarationDTOByID: " + "NIE ZNALAZLEM SUBGROUP O PODANYM ID");
////		}
		return dto;
//		return result;
	}
	
	
	public static void saveOrUpdateCSDeclaration(CSDeclarationDTO csD) {
		CSDeclarationDTO dto = (CSDeclarationDTO)declarations.get(new Long (csD.getId()));
		
		if (dto == null) {
			//dodajemy nowe dto do cache
			dto = new CSDeclarationDTO(csD.getId(), csD.getGroupID(), csD.getSubgroupTypeID(), csD.getSubjectID(), csD.getDuration(), csD.getToSchedule());
//			dto = new CSDeclarationDTO(csD.getId(), csD.getGroupID(), csD.getSubgroupTypeID(), csD.getSubjectID(), csD.getSubgroupsAmount(), csD.getDuration(), csD.getToSchedule());
			declarations.put(new Long(csD.getId()), dto);
		} else {
			//updateujemy dto istniejace juz w cache
			dto.setDuration(csD.getDuration());
			dto.setGroupID(csD.getGroupID());
//			dto.setSubgroupsAmount(csD.getSubgroupsAmount());
			dto.setSubgroupTypeID(csD.getSubgroupTypeID());
			dto.setSubjectID(csD.getSubjectID());
		}
	}
	
	/**
	 * Usuwa z cache'u rekord.
	 * @param csD
	 */
	public static void removeCSDeclaration(CSDeclarationDTO csD) {
		declarations.remove(new Long(csD.getId()));
		
//		CSDeclarationDTO dto = (CSDeclarationDTO)declarations.get(new Long (csD.getId()));
	}
	
	
	//pobiera z cache deklaracje grupy o wskazanym id	
	public static CSDeclarationDTO[] getDeclarationsByGroupID(long groupID) {
		//CSSubgroupDTO[] result = new CSSubgroupDTO[subgroups.size()];
		List<CSDeclarationDTO> result = new ArrayList<CSDeclarationDTO>();
		
//		int i=0;
		for (Iterator<CSDeclarationDTO> it = declarations.values().iterator(); it.hasNext();) {
			CSDeclarationDTO d = (CSDeclarationDTO) it.next();
			if (d.getGroupID() == groupID) {
				CSDeclarationDTO newD = new CSDeclarationDTO(d.getId(), d.getGroupID(), d.getSubgroupTypeID(), d.getSubjectID(), new Integer(d.getDuration()), new Integer(d.getToSchedule()));
//				CSDeclarationDTO newD = new CSDeclarationDTO(d.getId(), d.getGroupID(), d.getSubgroupTypeID(), d.getSubjectID(), new Long(d.getSubgroupsAmount()), new Integer(d.getDuration()), new Integer(d.getToSchedule()));
				result.add(newD);
			}
		}
		
		CSDeclarationDTO[] resultA = (CSDeclarationDTO[]) result.toArray(new CSDeclarationDTO[0]); 
		return resultA;
	}
	
	//podaje liczbe podgrup podpietych do wskazanej grupy, o wskazanym typie	
	public static int getSubgroupsCountByGroupIDAndSubgroupTypeID(long groupID, long subgroupTypeID) {
		//CSSubgroupDTO[] result = new CSSubgroupDTO[subgroups.size()];
		int counter = 0;
		
		for (Iterator<CSSubgroupDTO> it = subgroups.values().iterator(); it.hasNext();) {
			CSSubgroupDTO sg = (CSSubgroupDTO) it.next();
			if (sg.getGroupID() == groupID && sg.getSubgroupTypeID() == subgroupTypeID) {
				counter++;
			}
		}
		
		return counter;
	}
	
	//podaje tablice z idkami do podgruppodpietych do wskazanej grupy, o wskazanym typie	
	public static Long[] getSubgroupsIDsByGroupIDAndSubgroupTypeID(long groupID, long subgroupTypeID) {
		List<Long> list = new ArrayList<Long>();
		
		for (Iterator<CSSubgroupDTO> it = subgroups.values().iterator(); it.hasNext();) {
			CSSubgroupDTO sg = (CSSubgroupDTO) it.next();
			if (sg.getGroupID() == groupID && sg.getSubgroupTypeID() == subgroupTypeID) {
				list.add(new Long(sg.getId()));
			}
		}
		
		return list.toArray(new Long[0]);
	}


	
	
//	/**
//	 * @param mrs
//	 */
//	private static void notifyReceivers(final PCompositeRequest request) {
//		if (mrs != null) {
//			for (int j = 0; j < mrs.length; j++) {
//				mrs[j].notifyAboutReturningResponse();
//			}
//		}
//	}

	
}
